「 Velero 」源码走读 — Server
based on v1.6.3
Config
pkg/client/factory.go
pkg/client/config.go
pkg/cmd/velero/velero.go
Velero 的全局配置参数,比如 namespaces,features,cacert 和 colorized 等信息,是在初始化 velero 根 command 时,解析位于 host 的 <HOME>/.config/velero/config.json 的配置文件获取配置对象,初始化 factory 对象,将其透传给下级子 command 实现,由于 velero 服务的启动也是 velero 的子命令(即 velero server),因此实现了全局配置透传功能。
Generic Controller
pkg/controller/generic_controller.go
pkg/controller/interface.go
internal/util/managercontroller/managercontroller.go
顾名思义,Generic Controller 定义所有 Controller 的通用行为,本身负责周期性调用 Controller 注册的方法处理 Key,维护 Controller Key 的生命周期。
每一个 Controller 都继承了 Generic Controller,主要包括注册 syncHandler 和 resyncFunc,以及 queue 和 cacheSyncWaiters 等。
Generic Controller 主要包含以下核心属性:
queue
默认使用 K8s 提供的 NewNamedRateLimitingQueue,队列中就是需要处理的 Key,格式为 <namespace>/<name> 或者 <name>(取决于对象是否是 namespaced scope)。
Generic Controller 提供了 enqueue 的方法,用于 Key 的入队(本质上就是 queue 的 Add 方法,只不过转换成了上述的格式)。
syncHandler
Generic Controller 会周期性的调用 Controller 注册的 syncHandler,处理 queue 中的 Key。
resyncFunc
Generic Controller 会根据 resyncPeriod 周期性的调用 Controller 注册的 resyncFunc,执行额外声明的逻辑。
cacheSyncWaiters
Generic Controller 在执行 syncHandler 和 resyncFunc 之前会等待注册在 cacheSyncWaiters 全部缓存完成(本质上,就是一组 func() bool 均返回 true 即可,只不过传入的均为 podInformer.HasSynced 函数)。
Run
Generic Controller 的核心逻辑
- 校验 syncHandler 和 resyncFunc 是否至少注册了一个
- 如果注册了 cacheSyncWaiters,则等待其缓存同步完成
PodVolumeBackup Controller 和 PodVolumeRestore Controller 均注册了 cacheSyncWaiters,用于同步 Pod、PVC 以及 PodVolumeBackup(PodVolumeRestore) - 启动指定 worker 数量的 Goroutine,每 1 秒钟处理一次以下逻辑
该逻辑本身是死循环,只有在 queue 关闭时返回 false,因此隔 1 秒钟还会重新执行- 从 queue 中获取 Key(Get)
- 调用 syncHandler 注册的 Handler,处理 Key
- 如果处理成功,则在 queue 中移除(Forget)
- 如果处理失败,则限制速率重新加入 queue 中(AddRateLimited)
- 每隔 resyncPeriod 执行一次 resyncFunc 逻辑
resyncFunc 的处理不一定和 Key 相关,可以执行一些指标上报等操作,例如 Backup Controller 的 resyncFunc 实现
Runable
用于将调用 Run 函数启动 Controller 的方法封装成 manager.Runable 返回,供 manager.Add 以及 manager.Start 使用
manager 为 controller-runtime 的 manager
Velero Server
pkg/cmd/server/server.go
本质上是 velero cli 的 server 子命令,根据 install 以及更多的自定义参数,启动 Velero 服务。
newServer
工厂函数
- 设置 client 的 QPS 和 Burst,最终会作用在 Kube Client,Velero Client 和 Dynamic Client
- 初始化 Kube Client,Velero Client 和 Dynamic Client
- 初始化 PluginRegistry,发现注册在 /plugins 目录下的所有插件,并调用 velero run-plugins 命令启动插件的 GRPC 服务
插件包括 item-action、objectStore 以及 volumeSnapshotter 等 - 如果 Velero 开启了 CSI 特性,则初始化 CSI Snapshot Client
- 构建 controller-runtime 的 manager 对象
- 初始化 CredentialFileStore,用于操作认证文件信息
- 根据以上内容,构建 server 对象
run
server 运行的主体逻辑
- 如果配置了 profile 地址,则启动 pprof 服务
- 检查 Velero namespace 是否存在,如果不存在则报错
- 初始化 DiscoveryHelper,每 5 分钟刷新一次,获取可以备份的对象信息
- 检查 Velero 服务所需要的 CRD 是否存在,如果不存在则报错
- 检查 Restic 是否存在,如果不存在则输出 warning 信息,确保 restic 所需要的 secret 存在(即 velero-restic-credentials),初始化 RepositoryManager
- 调用 runControllers,启动所有的 Controller
runControllers
启动 controller 以及其他服务
- 启动 promHttp 服务,对接 Prometheus
- 初始化 pluginManager,提供与 Velero Plugin 交互的原生接口
- 初始化 backupStoreGetter,提供操作 Backup 和 Restore 的上层接口
即 Provider 章节中的 StorageProvider - 按需初始化 CSI Snapshot Lister 和 CSI SnapshotContent Lister
- 根据以上内容,初始化 Backup Controller、BackupSync Controller、Schedule Controller、GC Controller、BackupDeletion Controller、Restore Controller 以及 ResticRepo Controller,并将这些初步设定为默认开启的 Controller
- 此外,ServerStatusRequest Controller 和 DownloadRequest Controller 作为服务运行时的状态 Controller,也会作为默认开启
该类型的 Controller 与步骤 5 中的 Controller 处理逻辑相同,但是是分开处理和启动的 - 如果 Velero 服务为 restoreOnly 模式,则禁用 Backup Controller、Schedule Controller、GC Controller 以及 BackupDeletion Controller
- 将启用的 Controller 和禁用的 Controller 取差集后,即为最终 Velero 服务中启动的 Controller 信息
- 等待 Velero Client 和 CSI Snapshot Client 同步缓存(waitForCacheSync)
- 启动 BackupStorageLocation Controller(Reconciler 方式),按需启动 ServerStatusRequest Controller 和 DownloadRequest Controller
- 启动剩余的 Controller(不包含 Request 类型的 Controller),所有的 Controller 默认均为 1 worker
Restic Server
pkg/cmd/cli/restic/server.go
本质上是 velero restic cli 的 server 子命令,根据自定义参数,启动 Restic 服务。
newResticServer
- 初始化 KubeClient 和 Velero Client
- 初始化 PodInformer,仅获取调度在本节点上的 Pod
- 构建 controller-runtime 的 manager 对象
- 根据以上内容,构建 restic server 对象
- 判断挂载在 restic 服务中 /hosts_pods 目录下所有的 Pod 信息和集群中的所有的 Pod 是否一一对应
run
- 启动 promHttp 服务,对接 Prometheus
- 初始化 CredentialFileStore,用于操作认证文件信息
- 根据以上内容,初始化 PodVolumeBackup Controller 和 PodVolumeRestore Controller
- 启动 PodVolumeBackup Controller 和 PodVolumeRestore Controller,默认均为 1 worker
Velero Restic Restore Helper
cmd/velero-restic-restore-helper/main.go
本质是 Velero 项目的另一个 binary 执行文件(还有一个是 velero 本身),在恢复 Pod 卷数据时,会给该 Pod 注入一个 InitContainer,该 binary 就是 InitContainer 所用镜像(velero/velero-restic-restore-helper:<velero-version>)中的启动服务。
main
每一个待恢复卷数据的 Pod 的 InitContainer 中运行的服务
- 命令行接受一个参数,即 Restore 的 UID
- 启动死循环定时器,每一秒钟检查 InitContainer 的 /restores 目录下每一个子目录的 .velero 目录下是否有所提供的 Restore UID 文件,如果每一个子目录都有该 UID 文件,则认为恢复完成,退出死循环,该 InitContainer 生命周期结束,否则,继续等待,无超时时间
/restores 下每一个子目录代表一个待恢复的卷,命名为 Pod 使用的 PVC volumeMount 名称
「 Velero 」源码走读 — Server
http://shenxianghong.github.io/2022/03/06/2022-03-06 Velero 源码走读 - Server/